package com.dmm.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.dmm.search.pojo.ItemDoc;
import com.dmm.search.pojo.RequestParams;
import com.dmm.search.service.SearchService;
import com.hmall.common.dto.PageDTO;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public PageDTO<ItemDoc> searchItem(RequestParams params) {
        try {
            SearchRequest searchRequest = new SearchRequest("item");
            // 准备DSL语句
            // query条件
            buildBasicQuery(params, searchRequest);
            // 分页
            int page = params.getPage();
            int size = params.getSize();
            searchRequest.source().from((page - 1) * size).size(size);
            // 排序
            String sortBy = params.getSortBy();
            if ("sold".equals(sortBy)) {
                searchRequest.source().sort(sortBy, SortOrder.DESC);
            } else if ("price".equals(sortBy)) {
                searchRequest.source().sort(sortBy, SortOrder.ASC);
            }

            // 高亮
            searchRequest.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
            // 发送请求

            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            // 解析响应结果
            SearchHits hits = searchResponse.getHits();
            // 总条数
            long total = hits.getTotalHits().value;
            // 数据
            SearchHit[] hitsHits = hits.getHits();

            ArrayList<ItemDoc> arrylist = new ArrayList<>();
            for (SearchHit hitsHit : hitsHits) {
                // 获取文档source
                String json = hitsHit.getSourceAsString();
                // 反序列化转成java对像
                ItemDoc itemDoc = JSON.parseObject(json, ItemDoc.class);
                arrylist.add(itemDoc);
            }
            return new PageDTO<>(total,arrylist);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    private static void buildBasicQuery(RequestParams params, SearchRequest searchRequest) {
        // 构建booleanQuery
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 获取用户搜索词
        String key = params.getKey();
        // 如果用户搜索词为空，则默认查询全部
        if (key == null || "".equals(key)) {
            // 关键字搜索must
            boolQueryBuilder.must(QueryBuilders.matchAllQuery());
        } else {
            // 根据关键词查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("all", key));
        }

        // 品牌条件
        String brand = params.getBrand();
        if (brand != null && !"".equals(brand)) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("brand", brand));
        }

        // 分类条件
        String category = params.getCategory();
        if (category != null && !"".equals(category)) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("category", category));
        }

        // 价格条件
        Long minPrice = params.getMinPrice();
        Long maxPrice = params.getMaxPrice();
        if (minPrice != null && maxPrice != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(minPrice*100).lte(maxPrice*100));
        }

        // 算分
        FunctionScoreQueryBuilder functionScoreQueryBuilder =
                QueryBuilders.functionScoreQuery(
                        // 原始查询，做相关性算分
                        boolQueryBuilder,
                        // Function score 数组
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                                // 一个具体的Function score元素
                                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                        // 过滤条件
                                        QueryBuilders.termQuery("isAD", true),
                                        // 算分函数
                                        ScoreFunctionBuilders.weightFactorFunction(10)
                                )
                        });

        searchRequest.source().query(functionScoreQueryBuilder);
    }
}
